#include "Mesh.h"
#include "DirectX.h"
#include "ENUM.h"
#include "Definitions.h"
#include <string>
using namespace std;

Mesh::Mesh()
{
	device = DirectXFramework::Instance()->getDevice();
	D3DXMatrixTranslation(&meshTranslate, 0.0f, 0.0f, 0.0f);	// Translation
	D3DXMatrixRotationYawPitchRoll(&meshRotate, 0, 0, 0);		// Rotation
	D3DXMatrixScaling(&meshScale, 0.5f, 0.5f, 0.5f);			// Scaling
	currentTexture = 0;
	maxTextures = 0;
	//material = new Material;
}

Mesh::Mesh(char* file)
{
	device = DirectXFramework::Instance()->getDevice();
	D3DXMatrixTranslation(&meshTranslate, 0.0f, 0.0f, 0.0f);	// Translation
	D3DXMatrixRotationYawPitchRoll(&meshRotate, 0, 0, 0);		// Rotation
	D3DXMatrixScaling(&meshScale, 0.5f, 0.5f, 0.5f);			// Scaling
	Load(file);
	currentTexture = 0;
	maxTextures = 0;
	//material = new Material;
}
Mesh::~Mesh()
{
	//if(material)
	//{
	//	//delete [] material;
	//	//material = NULL;
	//}
	if(meshMaterials)
	{
		delete [] meshMaterials;
		meshMaterials = NULL;
	}
	if(instance)
	{
		instance->Release();
		instance = NULL;
	}
}
//find and load mesh file
void Mesh::Load(char* name)
{
	D3DXLoadMeshFromX(name, D3DXMESH_MANAGED, DirectXFramework::Instance()->getDevice(), &AdjBuffer, &XMaterials, &XEffects, &numMaterials, &instance);
	D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)XMaterials->GetBufferPointer();
	meshMaterials	= new D3DMATERIAL9[numMaterials];
	meshTextures	= new LPDIRECT3DTEXTURE9[numMaterials];
	for(DWORD i = 0; i < numMaterials; ++i)
	{
		meshMaterials[i] = d3dxMaterials[i].MatD3D;
		meshTextures[i] = NULL;
		if (d3dxMaterials[i].pTextureFilename)
		{
			//int len = 0;
			//len = (int)strlen(d3dxMaterials[i].pTextureFilename) + 1;
			//char *ucString = new char[len];
			//strcpy(ucString, (char*)d3dxMaterials[i].pTextureFilename);
			//LPCSTR filename = (LPCSTR)ucString;
			//D3DXCreateTextureFromFile(DirectXFramework::Instance()->getDevice(), filename, &meshTextures[i]);

			/**********************************************************/
			//WILL'S CODE
			std::string sFile(d3dxMaterials[i].pTextureFilename);
			D3DXCreateTextureFromFile(DirectXFramework::Instance()->getDevice(), sFile.c_str(), &meshTextures[i]);
			/**********************************************************/
		}
	}
}

void Mesh::Load(char* name, int numTextures)
{
	maxTextures = numTextures;
	D3DXLoadMeshFromX(name, D3DXMESH_MANAGED, DirectXFramework::Instance()->getDevice(), &AdjBuffer, &XMaterials, &XEffects, &numMaterials, &instance);
	meshTextures = new LPDIRECT3DTEXTURE9[maxTextures];
}

void Mesh::LoadNextTexture(char* name)
{
	if(currentTexture >= maxTextures)
		return;
	D3DXCreateTextureFromFile(DirectXFramework::Instance()->getDevice(), name, &meshTextures[currentTexture]);
	currentTexture++;
}

void Mesh::LoadTexture(int tex, char* name)
{
	std::string sFile("./Assets/Sprite_Textures/" + std::string(name));
	D3DXCreateTextureFromFile(DirectXFramework::Instance()->getDevice(), sFile.c_str(), &(meshTextures[tex]));
}

//draw mesh at stored location
void Mesh::Draw()
{
	D3DXMATRIX transMat, rotMat, scaleMat, worldMat;

	transMat = meshTranslate;
	scaleMat = meshScale;
	rotMat = meshRotate;

	D3DXMatrixMultiply(&scaleMat, &scaleMat, &rotMat);		// Multiply scale and rotation, store in scale
	D3DXMatrixMultiply(&worldMat, &scaleMat, &transMat);	// Multiply scale and translation, store in world

	device->SetTransform(D3DTS_WORLD, &worldMat);

	for (DWORD i = 0; i < numMaterials; ++i)
	{
		device->SetMaterial(&meshMaterials[i]);    // set the material for the subset
		device->SetTexture(0, meshTextures[i]);    // ...then set the texture
		instance->DrawSubset(i);
	}
}

//draw mesh at specific x and z
void Mesh::Draw(float TransX, float TransZ)
{
	D3DXMATRIX transMat, rotMat, scaleMat, worldMat;
	scaleMat = meshScale;
	rotMat = meshRotate;

	D3DXMatrixTranslation(&transMat, TransX, 0, TransZ);	// Tranlate it to xz pos before draw
	D3DXMatrixMultiply(&scaleMat, &scaleMat, &rotMat);		// Multiply scale and rotation, store in scale
	D3DXMatrixMultiply(&worldMat, &scaleMat, &transMat);	// Multiply scale and translation, store in world

	device->SetTransform(D3DTS_WORLD, &worldMat);

	for (DWORD i = 0; i < numMaterials; ++i)
	{
		device->SetMaterial(&meshMaterials[i]);    // set the material for the subset
		device->SetTexture(0, meshTextures[i]);    // ...then set the texture
		instance->DrawSubset(i);
	}
}

//draw mesh at specific x and z, facing a specific direction
void Mesh::Draw(float TransX, float TransZ, int direction)
{
	D3DXMATRIX transMat, rotMat, scaleMat, worldMat;
	scaleMat = meshScale;
	float deg = 0;

	switch(direction)
	{
	case NORTH:
		deg = TILE_DIR_FACTOR*0.0f;
		break;
	case EAST:
		deg = TILE_DIR_FACTOR;
		break;
	case SOUTH:
		deg = TILE_DIR_FACTOR*2.0f;
		break;
	case WEST:
		deg = TILE_DIR_FACTOR*3.0f;
		break;
	}

	D3DXMatrixTranslation(&transMat, TransX, 0, TransZ);	// Tranlate it to xz pos before draw
	D3DXMatrixRotationYawPitchRoll(&rotMat, D3DXToRadian(deg), 0, 0);
	D3DXMatrixMultiply(&scaleMat, &scaleMat, &rotMat);		// Multiply scale and rotation, store in scale
	D3DXMatrixMultiply(&worldMat, &scaleMat, &transMat);	// Multiply scale and translation, store in world
	
	device->SetTransform(D3DTS_WORLD, &worldMat);
	//material->setToRed();
	for (DWORD i = 0; i < numMaterials; ++i)
	{
		//device->SetMaterial(&meshMaterials[i]);    // set the material for the subset
		//material->setToRed();
		device->SetTexture(0, meshTextures[i]);    // ...then set the texture
		instance->DrawSubset(0);
	}	

}

void Mesh::Draw(int tex, float TransX, float TransZ)
{
	D3DXMATRIX transMat, rotMat, scaleMat, worldMat;
	scaleMat = meshScale;
	rotMat = meshRotate;

	D3DXMatrixTranslation(&transMat, TransX, 0, TransZ);	// Tranlate it to xz pos before draw
	D3DXMatrixMultiply(&scaleMat, &scaleMat, &rotMat);		// Multiply scale and rotation, store in scale
	D3DXMatrixMultiply(&worldMat, &scaleMat, &transMat);	// Multiply scale and translation, store in world

	device->SetTransform(D3DTS_WORLD, &worldMat);

	device->SetTexture(0, meshTextures[tex]);    // ...then set the texture
	instance->DrawSubset(0);
}